package rapc;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;

/**
 *
 * @author moi
 */
public class EnsembleCas {

    private ArrayList<cas> ensemble_cas;

    public EnsembleCas(ArrayList<cas> c) {
        this.ensemble_cas = c;
    }

    public ArrayList<cas> getensemble_cas() {
        return ensemble_cas;
    }

    public ArrayList<cas> getVoisin(cas cible, float T, int K) {
        // T est le seuil (Threshold) de similarité minimum pour être considéré comme voisin de ce cas cible
        //donc le rayon du cercle sur les dessins.
        // K représente le nombre de cas voisins nécessaire et
        //suffisant pour qu'une classe de solution soit éligible comme candidate pour la solution cible
        // il servirait pour l'attribution par adaptation d'un descripteur inconnu du cas cible
        int plusProche;
        float plusProcheValeur = 0;
        float similarite = 0;
        ArrayList<cas> liste_cas_voisins = new ArrayList<cas>(); // la liste est vide au départ
       /*  System.out.println("cible:"+cible.TosString());
        for(int i=0;i<ensemble_cas.size();i++)
        {
        System.out.println("cas:"+i+":"+ensemble_cas.get(i).TosString());
        
        }*/


        for (int i = 0; i < this.ensemble_cas.size(); i++) {
            similarite = similarite(cible, ensemble_cas.get(i));
            //Comparer la description du cas cible avec la description du cas source suivant de la base de cas
            // et ajout dans la liste des cas voisin si assez proche.
            System.out.println("la similaritié entre le cas" + i + "et le cas cible" + similarite(cible, ensemble_cas.get(i)) + "\n");
            if (similarite >= T) {
                liste_cas_voisins.add(ensemble_cas.get(i));
                if (plusProcheValeur < similarite) {
                    plusProche = liste_cas_voisins.size() - 1;
                    plusProcheValeur = similarite;
                }

            }
        }

        if (liste_cas_voisins.isEmpty()) {
            System.out.println("Manque d'expérience pour ce type de cas cible \n");
            return liste_cas_voisins;
            //manque d'expérience pour ce type de cas cible
        }
        //return liste_cas_voisins.get(plusProche) si on veu juste le plus proche

        return liste_cas_voisins;
    }

    //les deux cas doivent avoir le meme
    //nombre et les meme type de descripteur
    public float similarite(cas a, cas b) {
        float similarite = 0;

        for (int i = 0; i < a.getDescripteur().size(); i++) {
            /*la on pourait rajouté une multiplication par le poid*/
            System.out.println("les descripteur des cas dans similarité cas:" + a.TosString() + "b:" + b.TosString());
            System.out.print("le poid de ce descriptuer" + (a.getDescripteur().get(i).getPoids()));
            similarite = (similarite + a.getDescripteur().get(i).similariteDescripteur(a.getDescripteur().get(i), b.getDescripteur().get(i),
                    a.getDescripteurCase().get(i), b.getDescripteurCase().get(i)));
        }

        System.out.println("similarité cas:" + a.TosString() + "vs cas:" + b.TosString() + ":" + similarite / a.getDescripteur().size() + "\n");
        return similarite / a.getDescripteur().size();
    }

    //prend en parametre un chemin avec un nom et sauvegarde
    public void save(String Chemin) throws IOException {

        File f = new File(Chemin);// créetion du fichier          
        f.createNewFile();

        FileWriter fstream = new FileWriter(f);//buffer du fichier          
        BufferedWriter print = new BufferedWriter(fstream);

        for (int i = 0; i < ensemble_cas.size(); i++) {

            //premier passage on sauvegarde la stucture des cas
            if (i == 0) {
                ArrayList<descripteur> desc = new ArrayList<descripteur>();
                desc = ensemble_cas.get(i).getDescripteur();

                //on dis que c'est des descripteurs
                print.write("#descriptors#");
                print.newLine();
                for (int j = 0; j < desc.size(); j++) {

                    print.write(desc.get(j).toString());
                    print.newLine();

                }

                //mainetant on indique que c'est des cas
                print.write("#cases#");
                print.newLine();
            }


            print.write(ensemble_cas.get(i).TosString());
            print.newLine();
        }

        print.close();
    }

    //prend en parametre un chemin avec un nom et sauvegarde
    public void open(String Chemin) throws IOException {



        String x = Chemin;


        if (x == null) {
            return;
        }


        File f = new File(x);
        if (x == null) {
            return;
        }

        if (!f.exists()) {
            return;
        }

        if (f != null) {

            FileInputStream fstream = new FileInputStream(f);
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String strLine;
            String type = "";


            ArrayList<descripteur> descripteurs = new ArrayList<descripteur>();

            boolean descriptor = false;
            boolean cases = false;

            while ((strLine = br.readLine()) != null) {

                //evite de rentrer le mot clef "#cases#"   
                if (strLine.equals("#cases#") || cases) {

                    descriptor = false;
                    cases = true;

                    if (!strLine.equals("#cases#")) {

                        cas moncas = new cas();

                        //tableau de valeur
                        String[] split = strLine.split(",");
                        ArrayList<String> tableau = new ArrayList<String>(Arrays.asList(split));
                        
                        System.out.println(descripteurs.size());

                        //on enregistre les tableau contenant les descripteuirs et les valeur
                        moncas.addListedescripteur(descripteurs);
                        moncas.addListeCas(tableau);

                        ensemble_cas.add(moncas);
                    }

                }

                if (strLine.equals("#descriptors#") || descriptor) {
                    descriptor = true;
                    cases = false;
                    //System.out.println(strLine);
                    
                    //evite de rentrer le mot clef  #descriptors#             
                    if (!strLine.equals("#descriptors#")) {

                        String[] split = strLine.split(";");
                        type = split[split.length - 1];


                        if (type.equals("Boolean")) {
                            //booléen

                            descripteurBool monbool = new descripteurBool();

                            monbool.setCaseId(split[0]);
                            monbool.setNom(split[1]);
                            monbool.setExplication(split[2]);
                            monbool.setNorm(Boolean.parseBoolean(split[3]));
                            monbool.setdefVal(Boolean.parseBoolean(split[4]));
                            monbool.Poids(Double.parseDouble(split[5]));

                            descripteurs.add(monbool);



                        }
                        if (type.equals("Numerique")) {

                            descripteurNumerique monum = new descripteurNumerique();


                            monum.setCaseId(split[0]);
                            monum.setNom(split[1]);
                            monum.setExplication(split[2]);
                            monum.setNorm(Double.parseDouble(split[3]));
                            monum.setMin(Double.parseDouble(split[4]));
                            monum.setMax(Double.parseDouble(split[5]));
                            monum.setDefault(Double.parseDouble(split[6]));
                            monum.Poids(Double.parseDouble(split[7]));

                            descripteurs.add(monum);

                        }
                        if (type.equals("String")) {

                            descripteurString monstring = new descripteurString();

                            monstring.setCaseId(split[0]);
                            monstring.setNom(split[1]);
                            monstring.setExplication(split[2]);
                            monstring.setDefault(split[3]);
                            monstring.setNormal(split[4]);
                            monstring.Poids(Double.parseDouble(split[5]));

                            descripteurs.add(monstring);
                        }
                    }
                }
            }
        }

    }

    public String TosString() {

        String chaine = "";

        for (int i = 0; i < ensemble_cas.size(); i++) {
            chaine += ensemble_cas.get(i).TosString();
            chaine += ",";
        }



        return chaine;//un cas au format string
    }
}
